var calc = function (expression) {
    expression = expression.replace(/\s/g, '')
        .replace(/\-\-/g, '+').replace(/(\+\-)|(\-\+)/g, '-');
    while (/\([^()]+\)/.test(expression)) {
        expression = expression.replace(/\(([^()]+)\)/,
            (_, exp) => calc_no_parentheses(exp)
        );
        expression = expression.replace(/\-\-/g, '+').replace(/(\+\-)|(\-\+)/g, '-').replace(/\*\+/g, '*').replace(/\/\+/g, '/');
    }
    return calc_no_parentheses(expression)
};

function calc_no_parentheses(exp) {
    var fn = {
        '+': (a, b) => a + b,
        '*': (a, b) => a * b,
        '/': (a, b) => b / a
    }
    //trim head +
    exp = exp.replace(/^\+*/, '').replace(/\s/g, '')
    //all sub as plus negative number
    exp = exp.replace(/\-/g, '+-');
    var nums = [];
    var opers = [];
    for (x of exp.match(/(-?\d+(\.\d+)?)|[+*/]/g)) {
        if (/[*/]/.test(x)) {
            if (opers.length && opers[opers.length - 1] != '+') nums.push(fn[opers.pop()](nums.pop(), nums.pop()));
            opers.push(x);
        } else if (x === '+') {
            if (opers.length === 0) {
                opers.push(x);
            } else {
                while (opers.length) nums.push(fn[opers.pop()](nums.pop(), nums.pop()));
                opers.push(x);
            }
        } else {
            nums.push(+x);
        }
    }
    while (opers.length) nums.push(fn[opers.pop()](nums.pop(), nums.pop()));
    return nums[0];
}
console.log(calc_no_parentheses('2 - 3 - 4'))